package com.saltedhashed.web; import java.io.IOException; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.hibernate.validator.constraints.impl.EmailValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.request.NativeWebRequest; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.saltedhashed.dao.UserDao; import com.saltedhashed.model.User; @Controller public class AuthenticationController { private static final Logger logger = LoggerFactory.getLogger(AuthenticationController.class); @Inject private UserContext context; @Inject private UserDao userDao; private EmailValidator emailValidator = new EmailValidator(); private RestTemplate restTemplate = new RestTemplate(); @RequestMapping("/persona/auth") @ResponseBody public String authenticateWithPersona(@RequestParam String assertion, @RequestParam boolean userRequestedAuthentication, HttpServletRequest request, HttpServletResponse httpResponse, Model model) throws IOException { if (context.getUser() != null) { return ""; } MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("assertion", assertion); params.add("audience", request.getScheme() + "://" + request.getServerName() + ":" + (request.getServerPort() == 80 ? "" : request.getServerPort())); PersonaVerificationResponse response = restTemplate.postForObject("https://verifier.login.persona.org/verify", params, PersonaVerificationResponse.class); if (response.getStatus().equals("okay")) { User user = userDao.find(response.getEmail()); if (user == null && userRequestedAuthentication) { return "/signup?email=" + response.getEmail(); } else if (user != null){ if (userRequestedAuthentication) { context.setUser(user); return "/"; } else { return ""; } } else { return ""; //in case this is not a user-requested operation, do nothing } } else { logger.warn("Persona authentication failed due to reason: " + response.getReason()); throw new IllegalStateException("Authentication failed"); } } @RequestMapping("/signup") public String socialSignupPage(@RequestParam String email, NativeWebRequest request, Model model) { User user = new User(); user.setEmail(email); model.addAttribute("user", user); return "signup"; } @RequestMapping("/auth/completeRegistration") public String completeRegistration(@RequestParam String email, NativeWebRequest request, Model model) { if (!emailValidator.isValid(email, null)) { return "redirect:/?message=Invalid email. Try again"; } User user = userDao.completeUserRegistration(email); context.setUser(user); return "redirect:/?message=Registration successful"; } @RequestMapping("/logout") public String logout(HttpSession session, HttpServletRequest request, HttpServletResponse response) { session.invalidate(); return "index"; } @JsonIgnoreProperties(ignoreUnknown=true) @SuppressWarnings("unused") private static class PersonaVerificationResponse { private String status; private String email; private String reason; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } } }